/**
 * 
 */
package org.rico.util;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import org.apache.commons.collections4.CollectionUtils;
import org.quartz.CronScheduleBuilder;
import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.matchers.GroupMatcher;

/**
 * 定时任务工具
 * @author rico
 *
 */
public class SchedulerUtil {
	
	/**
	 * 读取所有的任务
	 * @param scheduler
	 * @return
	 * @throws SchedulerException
	 */
	public static List<ScheduleJob> queryAll(Scheduler scheduler) throws SchedulerException {
		List<ScheduleJob> jobs = new ArrayList<>();
		
		GroupMatcher<JobKey> matcher = GroupMatcher.anyJobGroup();
		Set<JobKey> jobKeys = scheduler.getJobKeys(matcher);
		
		if(CollectionUtils.isEmpty(jobKeys)) {
			return jobs;
		}
		
		for(JobKey key : jobKeys) {
			// 一个Job可能对应多个Trigger
			List<? extends Trigger> triggers = scheduler.getTriggersOfJob(key);

			for(Trigger trigger : triggers) {
				ScheduleJob job = new ScheduleJob();
				job.setJobName(key.getName());
		        job.setJobGroup(key.getGroup());
		        job.setDesc("触发器:" + trigger.getKey());
		        
		        Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
		        job.setJobStatus(triggerState.name());
		        
		        if (trigger instanceof CronTrigger) {
		            CronTrigger cronTrigger = (CronTrigger) trigger;
		            String cronExpression = cronTrigger.getCronExpression();
		            job.setCronExpression(cronExpression);
		        }
		        
		        jobs.add(job);
			}
		}
		
		return jobs;
	}
	
	/**
	 * 读取运行中的任务
	 * @param scheduler
	 * @return
	 * @throws SchedulerException
	 */
	public static List<ScheduleJob> queryRunningTask(Scheduler scheduler) throws SchedulerException {
		List<JobExecutionContext> executingJobs = scheduler.getCurrentlyExecutingJobs();
		if(CollectionUtils.isEmpty(executingJobs)) {
			return null;
		}
		
		List<ScheduleJob> jobs = new ArrayList<ScheduleJob>(executingJobs.size());
		for (JobExecutionContext executingJob : executingJobs) {
		    JobDetail jobDetail = executingJob.getJobDetail();
		    JobKey jobKey = jobDetail.getKey();
		    
		    ScheduleJob job = new ScheduleJob();
		    job.setJobName(jobKey.getName());
		    job.setJobGroup(jobKey.getGroup());
		    
		    Trigger trigger = executingJob.getTrigger();
		    job.setDesc("触发器:" + trigger.getKey());
		    
		    Trigger.TriggerState triggerState = scheduler.getTriggerState(trigger.getKey());
		    job.setJobStatus(triggerState.name());
		    
		    if (trigger instanceof CronTrigger) {
		        CronTrigger cronTrigger = (CronTrigger) trigger;
		        String cronExpression = cronTrigger.getCronExpression();
		        job.setCronExpression(cronExpression);
		    }
		    
		    jobs.add(job);
		}
	
		return jobs;
	}
	
	/**
	 * 暂停任务
	 * @param scheduler
	 * @param jobGroup
	 * @param jobName
	 * @throws SchedulerException
	 */
	public static void pauseTask(Scheduler scheduler, String jobGroup, String jobName) throws SchedulerException {
		JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
		scheduler.pauseJob(jobKey);
	}
	
	/**
	 * 恢复任务
	 * @param scheduler
	 * @param jobGroup
	 * @param jobName
	 * @throws SchedulerException
	 */
	public static void resumeTask(Scheduler scheduler, String jobGroup, String jobName) throws SchedulerException {
		JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
		scheduler.resumeJob(jobKey);
	}
	
	/**
	 * 删除任务
	 * @param scheduler
	 * @param jobGroup
	 * @param jobName
	 * @throws SchedulerException
	 */
	public static void deleteTask(Scheduler scheduler, String jobGroup, String jobName) throws SchedulerException {
		// 删除任务后，所对应的trigger也将被删除
		JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
		scheduler.deleteJob(jobKey);
	}
	
	/**
	 * 立即运行，只会运行一次
	 * @param scheduler
	 * @param jobGroup
	 * @param jobName
	 * @throws SchedulerException
	 */
	public static void executeTaskOne(Scheduler scheduler, String jobGroup, String jobName) throws SchedulerException {
		JobKey jobKey = JobKey.jobKey(jobName, jobGroup);
		scheduler.triggerJob(jobKey);
	}
	
	
	/**
	 * 重新
	 * @param scheduler
	 * @param jobGroup
	 * @param jobName
	 * @throws SchedulerException
	 */
	public static void reschedule(Scheduler scheduler, String jobGroup, String jobName, String cronExpression) throws SchedulerException {
		TriggerKey triggerKey = TriggerKey.triggerKey(jobName, jobGroup);
		
		// 获取trigger，即在spring配置文件中定义的 bean id="myTrigger"
		CronTrigger trigger = (CronTrigger) scheduler.getTrigger(triggerKey);
		
		// 表达式调度构建器
		CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(cronExpression);
		
		// 按新的cronExpression表达式重新构建trigger
		trigger = trigger.getTriggerBuilder().withIdentity(triggerKey).withSchedule(scheduleBuilder).build();
		// 按新的trigger重新设置job执行
		scheduler.rescheduleJob(triggerKey, trigger);
	}
	
}
